#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>

#define LOG_FILE "/var/log/mydaemon.log"
#define PID_FILE "/var/run/mydaemon.pid"

// 信号处理函数
void handle_signal(int sig) {
    switch (sig) {
        case SIGHUP:
            // 重新加载配置
            break;
        case SIGTERM:
        case SIGINT:
            // 清理并退出
            unlink(PID_FILE);
            exit(EXIT_SUCCESS);
            break;
    }
}

// 记录日志
void write_log(const char *msg) {
    int fd = open(LOG_FILE, O_WRONLY | O_APPEND | O_CREAT, 0640);
    if (fd == -1) return; // 无法打开日志文件
    
    time_t now = time(NULL);
    char time_str[26];
    ctime_r(&now, time_str);
    time_str[24] = '\0'; // 去掉换行符
    
    char log_line[1024];
    snprintf(log_line, sizeof(log_line), "[%s] %s\n", time_str, msg);
    
    write(fd, log_line, strlen(log_line));
    close(fd);
}

int main() {
    pid_t pid, sid;
    FILE *pid_file;
    
    // 第一步：创建子进程并退出父进程
    pid = fork();
    if (pid < 0) {
        perror("fork失败");
        exit(EXIT_FAILURE);
    }
    if (pid > 0) {
        exit(EXIT_SUCCESS); // 父进程退出
    }
    
    // 第二步：创建新会话
    sid = setsid();
    if (sid < 0) {
        perror("setsid失败");
        exit(EXIT_FAILURE);
    }
    
    // 第三步：设置文件掩码
    umask(0);
    
    // 第四步：更改工作目录
    if (chdir("/") < 0) {
        perror("chdir失败");
        exit(EXIT_FAILURE);
    }
    
    // 第五步：关闭文件描述符
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
    
    // 第六步：重定向标准输入/输出/错误
    open("/dev/null", O_RDWR); // 标准输入 (0)
    dup(0); // 标准输出 (1)
    dup(0); // 标准错误 (2)
    
    // 第七步：写入PID文件
    pid_file = fopen(PID_FILE, "w");
    if (pid_file) {
        fprintf(pid_file, "%d\n", getpid());
        fclose(pid_file);
    }
    
    // 第八步：设置信号处理
    signal(SIGHUP, handle_signal);
    signal(SIGTERM, handle_signal);
    signal(SIGINT, handle_signal);
    
    // 守护进程主逻辑
    write_log("守护进程已启动");
    
    while (1) {
        write_log("守护进程正在运行...");
        sleep(60); // 每分钟记录一次
    }
    
    return 0;
}